package zyz.framework.service.impl;

import org.apache.commons.lang.CharUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import zyz.framework.dao.BaseMapper;
import zyz.framework.dao.dml.DmlItem;
import zyz.framework.dao.query.Condition;
import zyz.framework.dao.query.QueryItem;
import zyz.framework.dao.query.Where;
import zyz.framework.entity.NameValue;
import zyz.framework.entity.Page;
import zyz.framework.exception.ServiceException;
import zyz.framework.service.BaseService;
import zyz.framework.util.ApplicationContextUtil;
import zyz.framework.util.ColumnUtils;
import zyz.framework.util.ReflectUtil;
import zyz.framework.util.StringUtils;

import javax.persistence.Table;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;


@Service("baseService")
public class BaseServiceImpl implements BaseService {
    //查询条件
    public static final String EQ = Condition.EQ;
    public static final String GT = Condition.GT;
    public static final String GE = Condition.GE;
    public static final String LT = Condition.LT;
    public static final String LE = Condition.LE;
    public static final String IN = Condition.IN;
    public static final String NEQ = Condition.NEQ;
    public static final String LIKE = Condition.LIKE;
    public static final String LIKE_ALL = Condition.LIKE_ALL;
    public static final String NOT_IN = Condition.NOT_IN;
    public static final String NULL = Condition.NULL;
    public static final String NOT_NULL = Condition.NOT_NULL;


    public boolean isJotmTransaction = false;
    @Autowired
    private ApplicationContextUtil applicationContextUtil;

    /**
     * 设置事务类型，true:jotm false:jdbc
     *
     * @param isJotmTransaction
     */
    public void setJotmTransaction(boolean isJotmTransaction) {
        this.isJotmTransaction = isJotmTransaction;
    }

    @Override
    public Long insert(DmlItem dmlItem) throws ServiceException {
        dmlItem.setMethod("insert");
        validateParam(dmlItem);

        //Service调用，需要先对dmlItem做预处理
        if (!dmlItem.isFromController()) {
            if (dmlItem.getParams() == null || dmlItem.getParams().size() < 1)
                dmlItem.setParams(new ArrayList<NameValue>());

            StringBuffer param = new StringBuffer();
            StringBuffer fields = new StringBuffer();
            String keywordEscape = getDatabaseKeywordEscape();
            Map<String, Object> paramMap = new HashMap<String, Object>();
            for (NameValue nameValue : dmlItem.getParams()) {
                fields.append(",").append(keywordEscape).append(nameValue.getName()).append(keywordEscape);
                param.append(",").append("#{dmlItem.paramMap.").append(nameValue.getName()).append("}");

                paramMap.put(nameValue.getName(), nameValue.getValue());
            }

            dmlItem.setParamMap(paramMap);
            dmlItem.setParam(param.toString().substring(1));
            dmlItem.setFields(fields.toString().substring(1));
        }

        return (Long) executeDml(dmlItem);
    }

    @Override
    public Long insert(Object object) throws ServiceException {
        return this.insert("id", object);
    }

    @Override
    public Long insert(String pkColumn, Object object) throws ServiceException {
        if (object == null) return 0L;

        Class<?> clazz = object.getClass();

        //entity转List<NameValue>
        List<NameValue> nameValueList = new ArrayList<NameValue>();
        for (Field field : clazz.getDeclaredFields()) {
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }
            Object value = ReflectUtil.getFieldValue(object, field.getName());
            if (value != null) {
                String column = propertyColumn(field.getName());
                nameValueList.add(new NameValue(column, value));
            }
        }

        DmlItem dmlItem = new DmlItem();
        dmlItem.setParams(nameValueList);
        dmlItem.setPkColumn(pkColumn);
        dmlItem.setTableName(getTableName(clazz));
        Long result = insert(dmlItem);
        //插入成功，更新主键值到entity
        if (result > 0) {
            ReflectUtil.setFieldValue(clazz, pkColumn, result);
        }

        return result;
    }

    @Override
    public Long insert(String pkColumn, Map obj, Class<?> clazz) throws ServiceException {
        DmlItem dmlItem = new DmlItem();
        List<NameValue> params = new ArrayList<NameValue>();
        Map<String, Object> map = (Map<String, Object>) obj;
        for (String key : map.keySet()) {
            params.add(new NameValue(key, map.get(key)));
        }
        dmlItem.setParams(params);
        if (pkColumn != null) {
            dmlItem.setPkColumn(pkColumn);
        }
        dmlItem.setTableName(getTableName(clazz));
        return insert(dmlItem);
    }


    @Override
    public Integer update(DmlItem dmlItem) throws ServiceException {
        dmlItem.setMethod("update");
        validateParam(dmlItem);

        //Service调用，需要先对dmlItem做预处理
        if (!dmlItem.isFromController()) {
            if (dmlItem.getParams() == null) dmlItem.setParams(new ArrayList<NameValue>());

            StringBuffer fields = new StringBuffer();
            String keywordEscape = getDatabaseKeywordEscape();
            Map<String, Object> paramMap = new HashMap<String, Object>();
            for (NameValue nameValue : dmlItem.getParams()) {
                fields.append(",").append(keywordEscape).append(nameValue.getName()).append(keywordEscape).append("=");
                if (!StringUtils.isEmpty(nameValue.getExpression())) {
                    fields.append(nameValue.getExpression());
                } else {
                    fields.append("#{dmlItem.paramMap._").append(nameValue.getName()).append("}");
                    paramMap.put("_" + nameValue.getName(), nameValue.getValue());
                }
            }
            if (dmlItem.getWhereList() != null && dmlItem.getWhereList().size() > 0) {
                StringBuffer whereCondition = new StringBuffer();
                for (Where where : dmlItem.getWhereList()) {
                    if (where.getAnd() != null && where.getAnd().size() > 0) {
                        StringBuffer andCondition = new StringBuffer(" and (");
                        for (int i = 0; i < where.getAnd().size(); i++) {
                            generateAndCondition(andCondition, paramMap, where.getAnd().get(i), i, true);
                        }
                        whereCondition.append(andCondition.toString()).append(")");
                    } else {
                        generateAndCondition(whereCondition, paramMap, where, null, true);
                    }
                }
                dmlItem.setParam(whereCondition.toString());
            }
            dmlItem.setParamMap(paramMap);
            dmlItem.setFields(fields.toString().substring(1));
        }

        return (Integer) executeDml(dmlItem);
    }

    @Override
    public Integer updateByPk(String pkColumn, Map obj, Class<?> clazz) throws ServiceException {
        DmlItem dmlItem = new DmlItem();
        List<NameValue> params = new ArrayList<NameValue>();
        Map<String, Object> map = (Map<String, Object>) obj;
        String id = pkColumn == null ? "id" : pkColumn;
        for (String key : map.keySet()) {
            if (key.equals(id)) continue;
            params.add(new NameValue(key, map.get(key)));
        }
        dmlItem.setPkColumn(id);
        dmlItem.setId(map.get(id));
        dmlItem.setParams(params);
        dmlItem.setTableName(getTableName(clazz));
        return update(dmlItem);
    }

    @Override
    public Integer updateById(Object object) throws ServiceException {
        return this.updateById("id", object, false);
    }

    @Override
    public Integer updateById(Object object, boolean updateEmpty) throws ServiceException {
        return this.updateById("id", object, updateEmpty);
    }

    @Override
    public Integer updateById(String pkColumn, Object object) throws ServiceException {
        return this.updateById(pkColumn, object, false);
    }

    @Override
    public Integer updateById(String pkColumn, Object object, boolean updateEmpty) throws ServiceException {
        if (object == null) return 0;
        Class<?> clazz = object.getClass();
        //entity转List<NameValue>
        Object idValue = null;
        List<NameValue> nameValueList = new ArrayList<NameValue>();
        for (Field field : clazz.getDeclaredFields()) {
            if ("serialVersionUID".equals(field.getName())) {
                continue;
            }

            Object value = ReflectUtil.getFieldValue(object, field.getName());
            //主键
            if (columnToProperty(pkColumn).equals(field.getName())) {
                idValue = value;
                continue;
            }

            if (updateEmpty || value != null) {
                String column = propertyColumn(field.getName());
                nameValueList.add(new NameValue(column, value));
            }
        }

        DmlItem dmlItem = new DmlItem();
        dmlItem.setTableName(getTableName(clazz));
        dmlItem.setParams(nameValueList);

        //主键
        dmlItem.setId(idValue);
        dmlItem.setPkColumn(pkColumn);

        return this.update(dmlItem);
    }

    @Override
    public Integer delete(DmlItem dmlItem) throws ServiceException {
        dmlItem.setMethod("delete");
        validateParam(dmlItem);

        //Service调用，需要先对dmlItem做预处理
        if (!dmlItem.isFromController()) {
            if (dmlItem.getParams() == null) dmlItem.setParams(new ArrayList<NameValue>());

            StringBuffer param = new StringBuffer();
            String keywordEscape = getDatabaseKeywordEscape();
            Map<String, Object> paramMap = new HashMap<String, Object>();
            String condition = "";
            for (NameValue nameValue : dmlItem.getParams()) {
                condition = StringUtils.isEmpty(nameValue.getCondition()) ? "=" : nameValue.getCondition();
                param.append(" and ").append(keywordEscape).append(nameValue.getName()).append(keywordEscape).append(condition);
                param.append("#{dmlItem.paramMap.").append(nameValue.getName()).append("}");

                paramMap.put(nameValue.getName(), nameValue.getValue());
            }

            dmlItem.setParamMap(paramMap);
            dmlItem.setParam(param.toString().substring(1));
        }

        if (dmlItem.getId() == null && StringUtils.isEmpty(dmlItem.getParam()))
            throw new RuntimeException("参数错误，至少需要指定一个条件");

        return (Integer) executeDml(dmlItem);
    }

    @Override
    public Integer deleteById(String id, Class<?> clazz) throws ServiceException {
        return this.deleteById("id", id, clazz);
    }

    @Override
    public Integer deleteById(String pkColumn, String id, Class<?> clazz) throws ServiceException {
        DmlItem dmlItem = new DmlItem();
        dmlItem.setMethod("delete");
        dmlItem.setId(id);
        dmlItem.setPkColumn(pkColumn);
        dmlItem.setTableName(getTableName(clazz));

        return (Integer) executeDml(dmlItem);
    }

    /**
     * 执行新增、修改、删除
     *
     * @param dmlItem
     * @return
     * @throws ServiceException
     */
    private Object executeDml(DmlItem dmlItem) throws ServiceException {
        //获取要操作的表
        String tableName = dmlItem.getTableName();
        //Oracle数据库设置主键生成为sequence
        if ("insert".equals(dmlItem.getMethod()) && "oracle".equals(applicationContextUtil.getDatabaseType())) {
            String id = (StringUtils.isEmpty(dmlItem.getPkColumn())) ? "id" : dmlItem.getPkColumn();
            dmlItem.setFields(id + "," + dmlItem.getFields());
            dmlItem.setParam("#{dmlItem.id}," + dmlItem.getParam());
            dmlItem.setSequenceName("sq_" + tableName.substring(tableName.indexOf("_") + 1));
        }


        //根据module获取相应的dao
        Object clazz = getBaseMapper(dmlItem.getModule());

        Object result = null;
        try {
            //调用相应的方法执行dml
            Method method = clazz.getClass().getMethod(dmlItem.getMethod(), DmlItem.class);
            result = method.invoke(clazz, dmlItem);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(e);
        }

        //新增返回插入的主键值
        if ("insert".equals(dmlItem.getMethod())) {
            result = dmlItem.getId();
        }
        if ("update".equals(dmlItem.getMethod())) {
            result = dmlItem.getId();
        }

        return result;
    }

    @Override
    @SuppressWarnings("unchecked")
    public Map<String, Object> getOne(QueryItem queryItem) throws ServiceException {
        return getOne(queryItem, Map.class);
    }

    @Override
    public <T> T getOne(QueryItem queryItem, Class<T> clazz) throws ServiceException {
        validateParam(queryItem);

        //Pre process
        boolean isKeyNeedConvert = queryPreProcess(queryItem);

        //Do query
        T result = null;
        BaseMapper baseMapper = getBaseMapper(queryItem.getModule());
        try {
            result = baseMapper.getOne(queryItem, clazz);
        } catch (Exception e) {
            throw new ServiceException(e);
        }

        //Post process
        if (clazz.getName().equals(Map.class.getName())) {
            result = (T) queryPostProcess(result);
        }

/*		//Post process
		if(isKeyNeedConvert && "oracle".equals(getDatabaseType()) && clazz.getName().equals(Map.class.getName())) {
			result=(T)queryPostProcess(result);
		}*/

        return result;
    }

    @Override
    public Object getList(QueryItem queryItem) throws ServiceException {
        return getList(queryItem, Map.class);
    }

    @Override
    public <T> List<T> getList(QueryItem queryItem, Class<T> clazz) throws ServiceException {
        // validateParam(queryItem);

        //Pre process
        boolean isKeyNeedConvert = queryPreProcess(queryItem);

        //Do query
        List<T> result = null;
        BaseMapper baseMapper = getBaseMapper(queryItem.getModule());
        try {
            result = baseMapper.getList(queryItem, clazz);
        } catch (Exception e) {
            throw new ServiceException(e);
        }
/*		//Post process
		if(isKeyNeedConvert && "oracle".equals(getDatabaseType()) && clazz.getName().equals(Map.class.getName())) {
			result=(List<T>)queryPostProcess(result);
		}*/
        //Post process
        if (clazz.getName().equals(Map.class.getName())) {
            result = (List<T>) queryPostProcess(result);
        }
        return result;
    }

    @Override
    public <T> Page<T> getPage(QueryItem queryItem, Class<T> clazz) throws ServiceException {
        Integer pageNo = queryItem.getPage();
        Integer limit = queryItem.getLimit();
        queryItem.setPage(pageNo == null ? 1 : pageNo);
        queryItem.setLimit(limit == null ? 20 : limit);
        List<T> items = getList(queryItem, clazz);

        Page<T> page = new Page<T>();
        page.setItems(items);
        page.setPage(queryItem.getPage());
        page.setEpage(queryItem.getLimit());
        if (items != null && items.size() > 0) {
            page.setTotal_items(getListCount(queryItem));
        } else {
            page.setTotal_items(0);
        }

        return page;
    }

    @Override
    public Integer getListCount(QueryItem queryItem) throws ServiceException {
        //Pre process add by wp
        if (null == queryItem.getTableName()) {
            queryPreProcess(queryItem);
        }

        Integer count = null;
        BaseMapper baseMapper = getBaseMapper(queryItem.getModule());
        try {
            count = baseMapper.getListCount(queryItem);
        } catch (Exception e) {
            throw new ServiceException(e);
        }

        return count;
    }

    /**
     * 获取数据库类型
     *
     * @return
     */
    private String getDatabaseType() {
        return StringUtils.isEmpty(applicationContextUtil.getDatabaseType()) ? "mysql" : applicationContextUtil.getDatabaseType();
    }

    /**
     * 数据库关键字转义字符
     *
     * @return
     */
    public String getDatabaseKeywordEscape() {
        return "mysql".equalsIgnoreCase(getDatabaseType()) ? "`" : "";
    }

    /**
     * 逗号替换符号
     *
     * @return
     */
    public String getCommaReplacement() {
        return "[c]";
    }

    /**
     * 根据module获取相应的mapper
     *
     * @param module
     * @return
     */
    private BaseMapper getBaseMapper(String module) {
        module = StringUtils.isEmpty(module) ? "base" : module;
        Object mapper = applicationContextUtil.getBean((isJotmTransaction ? "jotm" : "") + module + "Mapper");
        return mapper == null ? null : (BaseMapper) mapper;
    }

    /**
     * 查询预处理
     *
     * @param queryItem
     * @return
     */
    private boolean queryPreProcess(QueryItem queryItem) {
        //Service调用，需要先对queryItem做预处理
        if (!queryItem.isFromController()) {
            StringBuffer whereCondition = new StringBuffer();
            Map<String, Object> params = new HashMap<String, Object>();
            for (Where where : queryItem.getWhere()) {
                if (where.getAnd() != null && where.getAnd().size() > 0) {
                    StringBuffer andCondition = new StringBuffer(" and (");
                    for (int i = 0; i < where.getAnd().size(); i++) {
                        generateAndCondition(andCondition, params, where.getAnd().get(i), i, false);
                    }
                    whereCondition.append(andCondition.toString()).append(")");
                } else {
                    generateAndCondition(whereCondition, params, where, null, false);
                }
            }
            queryItem.setParams(params);
            if (StringUtils.isEmpty(queryItem.getFields())) {
                queryItem.setFields("*");
            }
            queryItem.setWhereCondition(whereCondition.toString());
        }

        //根据module+function获取要操作的table
        // queryItem.setTableName(TableNameUtil.getProperty(queryItem.getModule() + "_" + queryItem.getFunction()));

        //查询字段处理(Oracle:转小写/mysql:添加关键字转义符)
        boolean isKeyNeedConvert = false;
        String keywordEscape = getDatabaseKeywordEscape();
        if (!"getListCount".equals(queryItem.getMethod()) && queryItem.isNeedHandelField()) {
            if ("*".equals(queryItem.getFields())) {
                isKeyNeedConvert = true;
            } else {
                StringBuffer fields = new StringBuffer();
                for (String temp : queryItem.getFields().split(",")) {
                    String alais = "";
                    String column = temp.trim();
                    int idx = column.lastIndexOf(" ");
                    if (idx > 0) {
                        alais = column.substring(idx + 1);
                        column = column.substring(0, idx);
                    } else {
                        alais = column;
                    }
                    if (!StringUtils.isEmpty(keywordEscape)) {
                        if ("1".equals(column))
                            fields.append(",").append(temp);
                        else
                            fields.append(",").append(column.equals(alais) ? (keywordEscape + column + keywordEscape) : temp);
                    } else {
                        fields.append(",").append(column).append(" \"").append(alais.toLowerCase()).append("\"");
                    }
                }
                queryItem.setFields(fields.toString().substring(1));
            }
        }
        String comma = this.getCommaReplacement();
        String fields = queryItem.getFields();
        if (fields.indexOf(comma) > 0) {
            fields = fields.replaceAll("\\[c\\]", ",");
            queryItem.setFields(fields);
        }

        //getList根据数据库类型添加分页语句
        Integer page = queryItem.getPage();
        Integer limit = queryItem.getLimit();

        if (limit != null) {
            page = page == null ? 1 : page;
            if ("mysql".equalsIgnoreCase(getDatabaseType())) {
                queryItem.setPageFooter("limit " + (page - 1) * limit + ", " + limit);
            } else if ("oracle".equalsIgnoreCase(getDatabaseType())) {
                queryItem.setPageHeader("select * from (select p.*, rownum r from (");
                queryItem.setPageFooter(") p where rownum < " + (page * limit - 1) + ") where r >= " + ((page - 1) * limit + 1));
            }
        }

        return isKeyNeedConvert;
    }

    private Object queryPostProcess(Object result) {
        if (result instanceof Map) {
            return keyConvert(result == null ? null : (Map) result);
        } else if (result instanceof List) {
            List<Map<String, Object>> newData = new ArrayList<Map<String, Object>>();
            List<Map<String, Object>> oldData = result == null ? new ArrayList<Map<String, Object>>() : (List) result;
            for (Map<String, Object> temp : oldData) {
                newData.add(keyConvert(temp));
            }

            result = newData;
        }

        return result;
    }

    /**
     * Oracle查询没指定查询字段，对=返回的map的Key转小写
     *
     * @param data
     * @return
     */
    private Map<String, Object> keyConvert(Map<String, Object> data) {
        if (data == null || data.size() <= 0) {
            return null;
        }

        Map<String, Object> newData = new HashMap<String, Object>();
        for (String key : data.keySet()) {
            newData.put(ColumnUtils.underline2Camel(key, true), data.get(key));
        }

        return newData;
    }

    /**
     * QueryItem/DmlItem参数检查
     *
     * @param obj
     * @throws ServiceException
     */
    private void validateParam(Object obj) throws ServiceException {
        if (obj instanceof QueryItem) {
            QueryItem queryItem = (QueryItem) obj;
            if (StringUtils.isEmpty(queryItem.getTableName())) {
                throw new RuntimeException("QueryItem参数错误，tableName不能为空");
            }
        } else if (obj instanceof DmlItem) {
            DmlItem dmlItem = (DmlItem) obj;
            if (StringUtils.isEmpty(dmlItem.getTableName())) {
                throw new RuntimeException("DmlItem参数错误，tableName不能为空");
            }
            if ("update".equals(dmlItem.getMethod())) {
                if (dmlItem.getId() == null && (dmlItem.getWhereList() == null || dmlItem.getWhereList().size() <= 0)) {
                    throw new ServiceException("DmlItem参数错误，缺少更新条件(id/whereList)");
                }
                if (dmlItem.getWhereList() == null || dmlItem.getWhereList().size() <= 0) {
                    if (dmlItem.getId() == null || StringUtils.isEmpty(dmlItem.getPkColumn())) {
                        throw new RuntimeException("DmlItem参数错误，id/pkColumn不能为空");
                    }
                }
            }
        }
    }

    /**
     * 生成and
     *
     * @param whereCondition
     * @param params
     * @param andIndex
     * @param isDml
     */
    private void generateAndCondition(StringBuffer whereCondition, Map<String, Object> params, NameValue nameValue, Integer andIndex, boolean isDml) {
        //Expression
        if (andIndex == null) andIndex = 1;
        String orAnd = nameValue.isOr() ? " or " : " and ";
        if (nameValue.getName() == null && nameValue.getValue() == null && nameValue.getExpression() != null) {
            // and ( "" a>1 or b<1 )
            whereCondition.append(andIndex == 0 ? " " : orAnd).append(nameValue.getExpression());
            return;
        }

        String keywordEscape = getDatabaseKeywordEscape();
        String key = keywordEscape + nameValue.getName() + keywordEscape;
        Object value = nameValue.getValue();
        String operation = nameValue.getCondition();

        String paramPrefix = isDml ? "#{dmlItem.paramMap." : "#{queryItem.params.";
        String paramKey = nameValue.getName() + (andIndex == null ? "" : andIndex);//多个条件时，相同字段，多个条件，a >1 and a in (2,3)
        if (IN.equals(operation) || NOT_IN.equals(operation)) {
            StringBuffer and = new StringBuffer();
            String inValue = value == null ? "" : value.toString();
            int index = 0;
            for (String temp : inValue.split(",")) {
                params.put(paramKey + index, temp);
                and.append(",").append(paramPrefix).append(paramKey + (index++)).append("}");
            }
            whereCondition.append(andIndex == 0 ? " " : orAnd).append(key).append(" ").append(operation).append(" ").append(" (").append(and.toString().substring(1)).append(")");
        } else if (NULL.equals(operation) || NOT_NULL.equals(operation)) {
            whereCondition.append(orAnd).append(key).append(" ").append(operation).append(" ");
        } else {
            if (LIKE.equals(operation) && value instanceof String) {
                value = value == null ? "" : value.toString() + "%";
            } else if (LIKE_ALL.equals(operation) && value instanceof String) {
                value = value == null ? "" : ("%" + value.toString() + "%");
            }
            params.put(paramKey, value);
            whereCondition.append(andIndex == 0 ? " " : orAnd).append(key).append(" ").append("likeall".equals(operation) ? "like" : operation).append(" ").append(paramPrefix).append(paramKey).append("}");
        }
    }


    private Map<String, String> columnToProperty(Set<String> columnSet) {
        Map<String, String> map = new HashMap<String, String>();
        for (String column : columnSet) {
            map.put(column, columnToProperty(column));
        }

        return map;
    }

    /**
     * 数据库字段名转entity属性
     *
     * @param columnName
     * @return
     */
    private String columnToProperty(String columnName) {
        if (StringUtils.isEmpty(columnName)) return "";

        char[] chars = columnName.toCharArray();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (c == '_') {
                int j = i + 1;
                if (j < chars.length) {
                    sb.append(org.apache.commons.lang.StringUtils.upperCase(CharUtils.toString(chars[j])));
                    i++;
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * entity属性转数据库字段名
     *
     * @return
     */
    private String propertyColumn(String property) {
        if (StringUtils.isEmpty(property)) return "";

        char[] chars = property.toCharArray();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (CharUtils.isAsciiAlphaUpper(c)) {
                sb.append("_" + org.apache.commons.lang.StringUtils.lowerCase(CharUtils.toString(c)));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 获取表名
     */
    private String getTableName(Class<?> clazz) {
        if (clazz.isAnnotationPresent(Table.class)) {
            Table table = clazz.getAnnotation(Table.class);
            if (table.name() != null) {
                return table.name();
            }
        }
        return null;
    }
}